package cn.craccd.sqlHelper.utils;

import java.lang.reflect.Field;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Component;

import cn.craccd.sqlHelper.config.CompositeIndex;
import cn.craccd.sqlHelper.config.InitValue;
import cn.craccd.sqlHelper.config.SingleIndex;
import cn.craccd.sqlHelper.config.Table;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;

@Component
@EnableAsync
public class AsyncUtils {
	Logger logger = LoggerFactory.getLogger(this.getClass());
	
	@Value("${spring.database.type}")
	String database;
	@Value("${spring.database.package}")
	String packageName;
	@Autowired
	JdbcTemplate jdbcTemplate;
	@Autowired
	SqlUtils sqlUtils;

	// 同步执行
	public void initTableSync(Class<?> clazz) {
		initTable(clazz);
	}
	
	// 异步线程池
	@Async("sqlThreadPool")
	public void initTable(Class<?> clazz) {
		Table table = clazz.getAnnotation(Table.class);
		if (table != null) {
			// 创建表
			sqlUtils.checkOrCreateTable(clazz);

			// 获取表所有字段
			String sql = "";
			if (database.equals("sqlite")) {
				sql = "PRAGMA TABLE_INFO(`" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "`)";
			} else if (database.equals("mysql")) {
				sql = "SHOW COLUMNS FROM `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "`";
			} else if (database.equals("postgresql")) {
				sql = "SELECT column_name as name FROM information_schema.columns " + //
						"WHERE table_schema='public' AND table_name='" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "'";
			}
			sqlUtils.logQuery(sqlUtils.formatSql(sql));
			List<Map<String, Object>> columns = jdbcTemplate.queryForList(sqlUtils.formatSql(sql));

			// 获取表所有索引
			if (database.equals("sqlite")) {
				sql = "PRAGMA INDEX_LIST(`" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "`)";
			} else if (database.equals("mysql")) {
				sql = "SHOW INDEX FROM `" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "`";
			} else if (database.equals("postgresql")) {
				sql = "SELECT " + //
						"A.INDEXNAME as name " + //
						"FROM PG_AM B " + //
						"LEFT JOIN PG_CLASS F ON B.OID = F.RELAM " + //
						"LEFT JOIN PG_STAT_ALL_INDEXES E ON F.OID = E.INDEXRELID " + //
						"LEFT JOIN PG_INDEX C ON E.INDEXRELID = C.INDEXRELID " + //
						"LEFT OUTER JOIN PG_DESCRIPTION D ON C.INDEXRELID = D.OBJOID, " + //
						"PG_INDEXES A " + //
						"WHERE " + //
						"A.SCHEMANAME = E.SCHEMANAME AND A.TABLENAME = E.RELNAME AND A.INDEXNAME = E.INDEXRELNAME " + //
						"AND E.SCHEMANAME = 'public' AND E.RELNAME = '" + StrUtil.toUnderlineCase(clazz.getSimpleName()) + "' ";//
			}
			sqlUtils.logQuery(sqlUtils.formatSql(sql));
			List<Map<String, Object>> indexs = jdbcTemplate.queryForList(sqlUtils.formatSql(sql));

			// 建立字段
			Field[] fields = ReflectUtil.getFields(clazz);
			for (Field field : fields) {
				// 创建字段
				if (!field.getName().equals("id")) {
					sqlUtils.checkOrCreateColumn(clazz, field.getName(), columns);
				}

				// 创建索引
				if (field.isAnnotationPresent(SingleIndex.class)) {
					SingleIndex singleIndex = field.getAnnotation(SingleIndex.class);
					sqlUtils.checkOrCreateIndex(clazz, field.getName(), singleIndex.unique(), indexs);
				}

				// 更新表默认值
				if (field.isAnnotationPresent(InitValue.class)) {
					InitValue defaultValue = field.getAnnotation(InitValue.class);
					if (defaultValue.value() != null) {
						sqlUtils.updateDefaultValue(clazz, field.getName(), defaultValue.value());
					}
				}
			}

			// 获取组合索引
			if (clazz.isAnnotationPresent(CompositeIndex.class)) {
				CompositeIndex compositeIndex = clazz.getAnnotation(CompositeIndex.class);
				sqlUtils.checkOrCreateIndex(clazz, compositeIndex.colums(), compositeIndex.unique(), indexs);
			}
		}
	}

}
